package cn.com.nes.site.module.service.iot;

import cn.com.nes.common.annotation.AgentTransactional;
import cn.com.nes.common.annotation.OpeTransactional;
import cn.com.nes.common.util.ParameterUtil;
import cn.com.nes.mybatis.agent.ope.entity.EquipmentControlParamCustom;
import cn.com.nes.mybatis.agent.ope.mapper.AStandardDataItemMapper;
import cn.com.nes.mybatis.agent.ope.mapper.EquipmentControlParamCustomMapper;
import cn.com.nes.mybatis.agent.ope.mapper.IsDeviceProtocolDataItemInfoMapper;
import cn.com.nes.mybatis.agent.system.entity.ProtocolDataItemAuth;
import cn.com.nes.mybatis.agent.system.entity.TParam;
import cn.com.nes.mybatis.agent.system.mapper.ProtocolDataItemAuthMapper;
import cn.com.nes.mybatis.agent.system.mapper.TParamMapper;
import cn.com.nes.site.entity.DataReq;
import cn.com.nes.site.entity.PageData;
import cn.com.nes.site.entity.iot.Auth;
import cn.com.nes.site.entity.iot.ProtocolDataItemAuthDto;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service
public class ProtocolAuthService {

    @Resource
    private EquipmentControlParamCustomMapper equipmentControlParamCustomMapper;

    @Resource
    private AStandardDataItemMapper standardDataItemMapper;

    @Resource
    private TParamMapper paramMapper;

    @Resource
    private ProtocolDataItemAuthMapper protocolDataItemAuthMapper;

    @Resource
    private IsDeviceProtocolDataItemInfoMapper dataItemInfoMapper;

    @Resource
    private ProtocolService protocolService;

    @OpeTransactional
    @AgentTransactional
    public PageData saveDataItemAuth(DataReq req) {
        final String protocolId = ParameterUtil.getString(req, "protocolId");
        final String manufactureId = protocolService.getProtocolManufactureId(protocolId, req);
        final String type = ParameterUtil.getString(req, "type");
        final JSONArray data = ParameterUtil.getJSONArray(req, "data");
        final ArrayList<String> fieldNames = new ArrayList<>();
        Map<String, List<Integer>> userAuthMap = new HashMap<>();
        for (int i = 0; i < data.size(); i++) {
            JSONObject jsonObject = data.getJSONObject(i);
            for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                if ("fieldName".equals(entry.getKey())) {
                    fieldNames.add(entry.getValue().toString());
                } else {
                    if (!userAuthMap.containsKey(entry.getKey())) {
                        userAuthMap.put(entry.getKey(), new ArrayList<>());
                    }
                    userAuthMap.get(entry.getKey()).add(Integer.parseInt(entry.getValue().toString()));
                }
            }
        }
        for (Map.Entry<String, List<Integer>> entry : userAuthMap.entrySet()) {
            String userType = entry.getKey();
            List<Integer> userAuths = entry.getValue();

            List<String> authedFieldNames = new ArrayList<>();
            for (int i = 0; i < userAuths.size(); i++) {
                final Integer t = userAuths.get(i);
                if (t == 1) {
                    authedFieldNames.add(fieldNames.get(i));
                }
            }
            if ("app".equals(userType)) {
                saveAppUserDataItemAuth(fieldNames, authedFieldNames, protocolId, type);
                updateEquipmentParamCustomSort(protocolId);
            } else {
                saveUserDataItemAuth(fieldNames, authedFieldNames, protocolId, userType, type, manufactureId);
            }
        }

        return PageData.ok();
    }

    public void saveUserDataItemAuth(List<String> fieldNames, List<String> authedFieldNames, String protocolId, String userType,
                                     String type, String manufactureId) {
//        if (CollUtil.isEmpty(fieldNames) || CollUtil.isEmpty(authedFieldNames)) {
//
//            return;
//        }
        List<ProtocolDataItemAuth> currentAuths = protocolDataItemAuthMapper.selectList(new QueryWrapper<ProtocolDataItemAuth>()
                .eq(ProtocolDataItemAuth.PROTOCOL_ID, protocolId)
                .eq(ProtocolDataItemAuth.USER_TYPE, userType)
                .in(ProtocolDataItemAuth.FIELD_NAME, fieldNames)
                .ne("control".equals(type), ProtocolDataItemAuth.CODE, ""));

        if (CollUtil.isNotEmpty(currentAuths)) {
            // 删除
            final Iterator<ProtocolDataItemAuth> it = currentAuths.iterator();
            while (it.hasNext()) {
                final ProtocolDataItemAuth auth = it.next();
                if (!authedFieldNames.contains(auth.getFieldName())) {
                    if ("control".equals(type)) {
                        final ProtocolDataItemAuth updateEntity = new ProtocolDataItemAuth();
                        updateEntity.setCode("");
                        protocolDataItemAuthMapper.update(updateEntity, new QueryWrapper<ProtocolDataItemAuth>()
                                .eq(ProtocolDataItemAuth.PROTOCOL_ID, protocolId)
                                .eq(ProtocolDataItemAuth.FIELD_NAME, auth.getFieldName())
                                .eq(ProtocolDataItemAuth.USER_TYPE, userType)
                                .ne(ProtocolDataItemAuth.CODE, ""));

                    } else {
                        protocolDataItemAuthMapper.delete(new QueryWrapper<ProtocolDataItemAuth>()
                                .eq(ProtocolDataItemAuth.PROTOCOL_ID, protocolId)
                                .eq(ProtocolDataItemAuth.FIELD_NAME, auth.getFieldName())
                                .eq(ProtocolDataItemAuth.USER_TYPE, userType));
                    }
                    it.remove();
                }
            }
            //
            for (ProtocolDataItemAuth auth : currentAuths) {
                authedFieldNames.remove(auth.getFieldName());
            }

        }

        if (CollUtil.isEmpty(authedFieldNames)) {
            return;
        }

        // 查询code
        Map<String, String> fieldCommandCodeMap = getFieldCommadMap(protocolId, authedFieldNames);

        // 更新，查询权限没有控制权限
        if ("control".equals(type)) {
            List<ProtocolDataItemAuth> queryAuths = protocolDataItemAuthMapper
                    .selectList(new QueryWrapper<ProtocolDataItemAuth>()
                            .eq(ProtocolDataItemAuth.PROTOCOL_ID, protocolId)
                            .eq(ProtocolDataItemAuth.USER_TYPE, userType)
                            .in(ProtocolDataItemAuth.FIELD_NAME, authedFieldNames)
                            .eq(ProtocolDataItemAuth.CODE, ""));
            if (CollUtil.isNotEmpty(queryAuths)) {
                for (ProtocolDataItemAuth queryAuth : queryAuths) {
                    if (fieldCommandCodeMap.containsKey(queryAuth.getFieldName())) {
                        queryAuth.setCode(fieldCommandCodeMap.get(queryAuth.getFieldName()));
                        protocolDataItemAuthMapper.updateById(queryAuth);
                    }
                    authedFieldNames.remove(queryAuth.getFieldName());
                }
            }
            if (CollUtil.isEmpty(authedFieldNames)) {
                return;
            }
        }

        // 新增
        for (String fieldName : authedFieldNames) {
            final ProtocolDataItemAuth insertEntity = new ProtocolDataItemAuth();
            insertEntity.setProtocolId(protocolId);
            insertEntity.setFieldName(fieldName);
            insertEntity.setUserType(userType);
            insertEntity.setManufactureId(manufactureId);
            if ("control".equals(type)) {
                if (fieldCommandCodeMap.containsKey(fieldName)) {
                    insertEntity.setCode(fieldCommandCodeMap.get(fieldName));
                }
            }
            protocolDataItemAuthMapper.insert(insertEntity);
        }

    }

    public void saveAppUserDataItemAuth(List<String> fieldNames, List<String> authedFieldNames, String protocolId, String type) {
//        if (CollUtil.isEmpty(fieldNames) || CollUtil.isEmpty(authedFieldNames)) {
//            return;
//        }

        if (CollUtil.isEmpty(fieldNames) ) {
            return;
        }

        /*
        List<EquipmentControlParamCustom> currentAuths = equipmentControlParamCustomMapper
                .selectList(new QueryWrapper<EquipmentControlParamCustom>()
                        .eq(EquipmentControlParamCustom.PROTOCOL_ID, protocolId)
                        .in(EquipmentControlParamCustom.FIELDNAME, fieldNames)
                        .eq(EquipmentControlParamCustom.SFSC, "0")
                        .ne("control".equals(type), EquipmentControlParamCustom.CODE, ""));

        if (CollUtil.isNotEmpty(currentAuths)) {
            // 删除
            Iterator<EquipmentControlParamCustom> it = currentAuths.iterator();
            while (it.hasNext()) {
                final EquipmentControlParamCustom auth = it.next();
                if (!authedFieldNames.contains(auth.getFieldName())) {

                    if ("control".equals(type)) {
                        final EquipmentControlParamCustom updateEntity = new EquipmentControlParamCustom();
                        updateEntity.setCode("");
                        equipmentControlParamCustomMapper.update(updateEntity, new QueryWrapper<EquipmentControlParamCustom>()
                                .eq(EquipmentControlParamCustom.PROTOCOL_ID, protocolId)
                                .eq(EquipmentControlParamCustom.FIELDNAME, auth.getFieldName())
                                .eq(EquipmentControlParamCustom.SFSC, "0")
                                .ne(EquipmentControlParamCustom.CODE, ""));
                    } else {
                        equipmentControlParamCustomMapper.delete(new QueryWrapper<EquipmentControlParamCustom>()
                                .eq(EquipmentControlParamCustom.PROTOCOL_ID, protocolId)
                                .eq(EquipmentControlParamCustom.FIELDNAME, auth.getFieldName()));
                    }
                    it.remove();
                }
            }

            for (EquipmentControlParamCustom auth : currentAuths) {
                authedFieldNames.remove(auth.getFieldName());
                equipmentControlParamCustomMapper.updateById(auth);
            }


        }
        */
        equipmentControlParamCustomMapper.delete(new QueryWrapper<EquipmentControlParamCustom>().eq(EquipmentControlParamCustom.PROTOCOL_ID, protocolId)
                .eq(EquipmentControlParamCustom.SFSC, "0")
                .eq(EquipmentControlParamCustom.TYPE, type)
        );


        if (CollUtil.isEmpty(authedFieldNames)) {
            return;
        }

        Map<String, String> fieldCommandCodeMap = null;
        if ("control".equals(type)) {
            fieldCommandCodeMap = getFieldCommadMap(protocolId, authedFieldNames);
        }else{
            fieldCommandCodeMap = getFieldCommadMap2(protocolId, authedFieldNames);
        }

//        if ("control".equals(type)) {
//            List<EquipmentControlParamCustom> queryAuths = equipmentControlParamCustomMapper
//                    .selectList(new QueryWrapper<EquipmentControlParamCustom>()
//                            .eq(EquipmentControlParamCustom.PROTOCOL_ID, protocolId)
//                            .eq(EquipmentControlParamCustom.SFSC, 0)
//                            .in(EquipmentControlParamCustom.FIELDNAME, authedFieldNames)
//                            .eq(EquipmentControlParamCustom.CODE, ""));
//            if (CollUtil.isNotEmpty(queryAuths)) {
//                for (EquipmentControlParamCustom queryAuth : queryAuths) {
//                    if (fieldCommandCodeMap.containsKey(queryAuth.getFieldName())) {
//                        queryAuth.setCode(fieldCommandCodeMap.get(queryAuth.getFieldName()));
//                        equipmentControlParamCustomMapper.updateById(queryAuth);
//                    }
//                    authedFieldNames.remove(queryAuth.getFieldName());
//                }
//            }
//            if (CollUtil.isEmpty(authedFieldNames)) {
//                return;
//            }
//        }

        // 新增
        for (String fieldName : authedFieldNames) {
            final EquipmentControlParamCustom insertEntity = new EquipmentControlParamCustom();
            insertEntity.setProtocolId(protocolId);
            insertEntity.setFieldName(fieldName);
            insertEntity.setSfsc(0);
            insertEntity.setCode("");
            insertEntity.setType(type);
//            if ("control".equals(type)) {
                if (fieldCommandCodeMap.containsKey(fieldName)) {
                    insertEntity.setCode(fieldCommandCodeMap.get(fieldName));
                }
//            }
            equipmentControlParamCustomMapper.insert(insertEntity);
        }

    }

    public void updateEquipmentParamCustomSort(String protocolId) {
        // 更新所有的设备的控制参数的序号
        List<EquipmentControlParamCustom> controlParams = equipmentControlParamCustomMapper
                .selectList(new QueryWrapper<EquipmentControlParamCustom>()
                        .eq(EquipmentControlParamCustom.PROTOCOL_ID, protocolId)
                        .eq(EquipmentControlParamCustom.SFSC, 0));
        if (CollUtil.isNotEmpty(controlParams)) {
            for (int i = 0; i < controlParams.size(); i++) {
                EquipmentControlParamCustom controlParam = controlParams.get(i);
                controlParam.setSort(i + 1);
                equipmentControlParamCustomMapper.updateById(controlParam);
            }
        }
    }

    private Map<String, String> getFieldCommadMap(String protocolId, Collection<String> newFields) {
        List<Map<String, String>> commandCodes = equipmentControlParamCustomMapper
                .getCommandCodeByProtocolId(protocolId, newFields);
        Map<String, String> fieldCommandCodeMap = new HashMap<>();
        if (CollUtil.isNotEmpty(commandCodes)) {
            for (Map<String, String> map : commandCodes) {
                String fieldName = map.get("fieldName");
                String code = map.get("code");
                String controlData = map.get("control_data");
                String relationDataItemIds = map.get("relation_data_item_ids");
                if (StrUtil.isNotBlank(controlData)) {
                    if(!controlData.equals(relationDataItemIds)){
                        code = "";
                    }
                }
                fieldCommandCodeMap.put(fieldName, code);
            }
        }
        // 查询标准项开关机
        String switchFields = standardDataItemMapper.getStandardSwitchCode(protocolId, newFields);
        if (StrUtil.isNotBlank(switchFields)) {
            fieldCommandCodeMap.put(switchFields, "01");
        }
        return fieldCommandCodeMap;
    }


    private Map<String, String> getFieldCommadMap2(String protocolId, Collection<String> newFields) {
        List<Map<String, String>> commandCodes = equipmentControlParamCustomMapper
                .getCommandCodeByProtocolId2(protocolId, newFields);
        Map<String, String> fieldCommandCodeMap = new HashMap<>();
        if (CollUtil.isNotEmpty(commandCodes)) {
            for (Map<String, String> map : commandCodes) {
                String fieldName = map.get("fieldName");
                String code = map.get("code");
                fieldCommandCodeMap.put(fieldName, code);
            }
        }
//        // 查询标准项开关机
//        String switchFields = standardDataItemMapper.getStandardSwitchCode(protocolId, newFields);
//        if (StrUtil.isNotBlank(switchFields)) {
//            fieldCommandCodeMap.put(switchFields, "01");
//        }
        return fieldCommandCodeMap;
    }

    public List<Map<String, Object>> getUserTypes() {
        final List<Map<String, Object>> userTypes = paramMapper.selectMaps(new QueryWrapper<TParam>()
                .select(TParam.VALUE, TParam.NAME)
                .eq(TParam.TYPE_NAME, "用户职务")
                .eq(TParam.IS_DELETE, 0)
                .orderByDesc(TParam.SORT)
                .orderByDesc(TParam.UUID));
        userTypes.add(MapBuilder.create(new HashMap<String, Object>())
                .put("value", "app")
                .put("name", "APP用户")
                .build());
        return userTypes;
    }

    public PageData getDataItemAuth(DataReq req) {
        final String protocolId = ParameterUtil.getString(req, "protocolId");
        final String type = ParameterUtil.getString(req, "type", "query");

        ProtocolDataItemAuthDto dto = new ProtocolDataItemAuthDto();
        final ArrayList<Auth> auths = new ArrayList<>();
        List<Map<String, String>> fieldInfos = dataItemInfoMapper.getAllFieldNames(protocolId, type);
        final List<Map<String, Object>> userTypes = getUserTypes();
        List<String> fields = new ArrayList<>();
        for (Map<String, String> field : fieldInfos) {
            String fieldName = field.get("fieldName");
            fields.add(fieldName);
        }
        for (Map<String, Object> userType : userTypes) {
            String value = (String) userType.get("value");
            Auth auth = new Auth();
            auths.add(auth);
            Set<String> userAuthSet = new HashSet<>();
            if ("app".equals(value)) {
                final List<EquipmentControlParamCustom> appAuths = equipmentControlParamCustomMapper
                        .selectList(new QueryWrapper<EquipmentControlParamCustom>()
                                .eq(EquipmentControlParamCustom.PROTOCOL_ID, protocolId)
                                .eq(EquipmentControlParamCustom.SFSC, 0)
                                .eq(EquipmentControlParamCustom.TYPE,type)
                                //.ne("control".equals(type), EquipmentControlParamCustom.CODE, "")
                                .orderByDesc(EquipmentControlParamCustom.SORT));
                for (EquipmentControlParamCustom appAuth : appAuths) {
                    userAuthSet.add(appAuth.getFieldName());
                }
            } else {
                final List<ProtocolDataItemAuth> userAuths = protocolDataItemAuthMapper
                        .selectList(new QueryWrapper<ProtocolDataItemAuth>()
                                .eq(ProtocolDataItemAuth.PROTOCOL_ID, protocolId)
                                .eq(ProtocolDataItemAuth.USER_TYPE, value)
                                .ne("control".equals(type), ProtocolDataItemAuth.CODE, "")
                                .orderByDesc(ProtocolDataItemAuth.FIELD_NAME));
                for (ProtocolDataItemAuth userAuth : userAuths) {
                    userAuthSet.add(userAuth.getFieldName());
                }
            }
            auth.setUserType(value);
            auth.setType(type);
            List<Integer> authFields = new ArrayList<>();
            for (String fieldName : fields) {
                authFields.add(userAuthSet.contains(fieldName) ? 1 : 0);
            }
            auth.setAuth(authFields);
        }

        dto.setUserTypes(userTypes);
        dto.setColumns(new ArrayList<>());
        for (int i = 0; i < fieldInfos.size(); i++) {
            Map<String, String> fieldInfo = fieldInfos.get(i);
            final Map<String, Object> e = new HashMap<>();
            dto.getColumns().add(e);
            e.put("dataItemName", fieldInfo.get("dataItemName"));
            e.put("setFieldName", fieldInfo.get("fieldName"));
            for (Auth auth : auths) {
                e.put(auth.getUserType(), auth.getAuth().get(i));
            }
        }
        return PageData.ok("authInfo", dto);
    }

}
